package optimizer;

import java.util.*;
import simulator.*;

public class Target {
	private GameState initial;
	private GameState minimumTarget;
	private GameState maximumTarget;
	
	public Target (GameState initial, GameState minimumTarget) {
		this.initial = initial;
		this.minimumTarget = new GameState(initial);		
		this.maximumTarget = new GameState(initial);
		this.setTarget(minimumTarget);
	}
	
	private void setTarget(GameState targetState) {
		
		for(GameAsset asset : GameAsset.values()) {
			int numAssetInTarget = targetState.getNumberOfAsset(asset);
			// for every asset which is in the target state
			if(numAssetInTarget > 0) {
				// running multiple times for each asset in targetState simplifies the code slightly
					// Restricts out targets to ONLY consisting of units, not buildings
				this.minimumTarget.addUnit(asset, numAssetInTarget);
				this.maximumTarget.addUnit(asset, numAssetInTarget);
				ArrayList<GameAsset> dependentAssets = OptimizerUtilities.getDependentAssets(new ArrayList<GameAsset>(), asset);
				
				for(GameAsset dependentAsset : dependentAssets) {
					if(dependentAsset != asset)	{
						// We only set the dependencies to each to 1 for minimum
						this.minimumTarget.setUnitNumber(dependentAsset, 1);
						
						// however for maximum we set the dependencies to the same number as there are in the target
						// because 6 barracks in theory might be useful to build 6 marines.
						// 7 barracks is obviously not useful, so this is how we stop our program choosing to do that.
						this.maximumTarget.addUnit(dependentAsset, numAssetInTarget);
					}
				}
			}
		}
		
		// Set the maximum number of minerals we should theoretically have at any one time. 
		// If we have more than this we've clearly gone wrong somewhere
		int requiredResource = OptimizerUtilities.calculateTotalMineralsRequired(
				OptimizerUtilities.getGameAssetArrayFromGameState(maximumTarget));
		this.maximumTarget.setUnitNumber(GameAsset.MINERAL, requiredResource);
		
		// Same again for the gas
		requiredResource = OptimizerUtilities.calculateTotalVespeneRequired(
				OptimizerUtilities.getGameAssetArrayFromGameState(maximumTarget));
		this.maximumTarget.setUnitNumber(GameAsset.VESPENE_GAS, requiredResource);
		
		if(requiredResource > 0) {
			this.minimumTarget.setUnitNumber(GameAsset.REFINERY, 1);
			this.maximumTarget.setUnitNumber(GameAsset.REFINERY, initial.getNumberOfAsset(GameAsset.VESPENE_GEYSER));
		}
		
		this.maximumTarget.setUnitNumber(GameAsset.WORKER, 3 * initial.getNumberOfAsset(GameAsset.MINERAL_PATCH));
		
		this.minimumTarget.addUnit(GameAsset.SUPPLY_DEPOT, 
				OptimizerUtilities.calculateAdditionalSupplyDepotsRequired(
						OptimizerUtilities.getGameAssetArrayFromGameState(this.minimumTarget)));
		
		
		this.minimumTarget.setUnitNumber(GameAsset.SUPPLY, 0);
		this.minimumTarget.setUnitNumber(GameAsset.MINERAL, 0);
		this.minimumTarget.setUnitNumber(GameAsset.VESPENE_GAS, 0);
	}

	public GameState getInitial() {
		return initial;
	}

	public GameState getMinimumTarget() {
		return minimumTarget;
	}

	public GameState getMaximumTarget() {
		return maximumTarget;
	}
	
}
